package com.naiterui.ehp.bs.consult.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.naiterui.common.redis.RedisUtil;
import com.naiterui.ehp.bp.domain.DrVideoConsult;
import com.naiterui.ehp.bp.utils.consult.VideoConsultUtil;
import com.naiterui.ehp.bs.consult.constant.VideoConsultConstant;
import com.naiterui.ehp.bs.consult.service.IVideoConsultNoticeService;
import com.naiterui.ehp.bs.consult.service.IVideoConsultService;
import com.naiterui.ehp.bs.consult.util.TrtcUtil;
import com.naiterui.ehp.bs.consult.vo.VideoConsultCacheVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

/**
 * 回调
 *
 * @author yangfuya
 * @version 1.0
 * @date 2021-03-01 14:33
 **/
@Slf4j
@Service
@RequiredArgsConstructor
public class VideoConsultNoticeServiceImpl implements IVideoConsultNoticeService {

    private final IVideoConsultService videoConsultService;

    private static final int EXPIRE = 3600 * 24;

    @Override
    public void createRoom(JSONObject json) {
        int roomId = json.getIntValue("RoomId");
        String userId = json.getString("UserId");
        boolean existsKey = RedisUtil.keyOps().existsKey(VideoConsultConstant.VIDEO_CONSULT_CACHE_KEY + roomId);
        if (!existsKey) {
            VideoConsultCacheVO cache = new VideoConsultCacheVO();
            cache.setRoomId(roomId);
            cache.setStatus(0);
            RedisUtil.valueOps().setEx(VideoConsultConstant.VIDEO_CONSULT_CACHE_KEY + roomId, JSON.toJSONString(cache), EXPIRE);
        }
        if (VideoConsultUtil.containsDoctor(userId)) {
            log.info("APP医生创建房间, roomId:{}, userId:{}", roomId, userId);
        } else if (VideoConsultUtil.containsDoctorPc(userId)) {
            log.info("PC医生创建房间, roomId:{}, userId:{}", roomId, userId);
        } else {
            log.info("患者创建房间, roomId:{}, userId:{}", roomId, userId);
        }
    }

    @Override
    public void dismissRoom(JSONObject json) {
        int roomId = json.getIntValue("RoomId");
        log.info("房间解散, roomId:{}", roomId);
        RedisUtil.keyOps().delete(VideoConsultConstant.VIDEO_CONSULT_SPECIALIST_CACHE_KEY + roomId);
    }

    @Override
    public void inRoom(JSONObject json) {
        int roomId = json.getIntValue("RoomId");
        String userId = json.getString("UserId");
        boolean existsKey = RedisUtil.keyOps().existsKey(VideoConsultConstant.VIDEO_CONSULT_CACHE_KEY + roomId);
        VideoConsultCacheVO cacheVO;
        if (!existsKey) {
            cacheVO = new VideoConsultCacheVO();
            cacheVO.setRoomId(roomId);
            cacheVO.setStatus(0);
            RedisUtil.valueOps().setEx(VideoConsultConstant.VIDEO_CONSULT_CACHE_KEY + roomId, JSON.toJSONString(cacheVO), EXPIRE);
        } else {
            String cacheStr = RedisUtil.valueOps().getString(VideoConsultConstant.VIDEO_CONSULT_CACHE_KEY + roomId);
            cacheVO = JSON.parseObject(cacheStr, VideoConsultCacheVO.class);
        }
        Integer status = cacheVO.getStatus();
        // PC端医生
        if (VideoConsultUtil.containsDoctorPc(userId)) {
            log.info("PC端医生进入房间, roomId:{}, userId:{}", roomId, userId);
            String id = VideoConsultUtil.getId(userId, VideoConsultUtil.DOCTOR_PC_PREFIX) + "";
            String doctorAppId = VideoConsultUtil.DOCTOR_PREFIX + id;
            String cacheUserId = RedisUtil.hashOps().hget(VideoConsultConstant.VIDEO_CONSULT_PERSONNEL_CACHE_KEY + roomId, doctorAppId);
            // 如果该医生id已存在，则把app端医生踢下线
            if (!StringUtils.isEmpty(cacheUserId)) {
                log.info("被踢用户医生id:{}", doctorAppId);
                TrtcUtil.removeUser(roomId, new String[]{doctorAppId});
                cacheVO.setStatus(VideoConsultCacheVO.DOCTOR_PC_AND_PATIENT_EXIST);
            }
            // 如果房间没人，则改为医生在
            if (VideoConsultCacheVO.NOT_EXIST == status) {
                cacheVO.setStatus(VideoConsultCacheVO.DOCTOR_PC_EXIST);
            }
            else if (VideoConsultCacheVO.PATIENT_EXIST == status) {
                if (null == cacheVO.getStartTime()) {
                    cacheVO.setStartTime(System.currentTimeMillis());
                }
                cacheVO.setStatus(VideoConsultCacheVO.DOCTOR_PC_AND_PATIENT_EXIST);
            }
            videoConsultService.updateVideoConsultStatus(roomId, null, null, id);
            RedisUtil.hashOps().hset(VideoConsultConstant.VIDEO_CONSULT_PERSONNEL_CACHE_KEY  + roomId, userId, id);
        }
        // APP端医生
        else if (VideoConsultUtil.containsDoctor(userId)) {
            log.info("APP端医生进入房间, roomId:{}, userId:{}", roomId, userId);
            String id = VideoConsultUtil.getId(userId, VideoConsultUtil.DOCTOR_PREFIX) + "";
            String doctorPcId = VideoConsultUtil.DOCTOR_PC_PREFIX + id;
            String cacheUserId = RedisUtil.hashOps().hget(VideoConsultConstant.VIDEO_CONSULT_PERSONNEL_CACHE_KEY + roomId, doctorPcId);
            // 如果该医生id已存在，则把pc端医生踢下线
            if (!StringUtils.isEmpty(cacheUserId)) {
                log.info("被踢用户医生id:{}", doctorPcId);
                TrtcUtil.removeUser(roomId, new String[]{doctorPcId});
                cacheVO.setStatus(VideoConsultCacheVO.DOCTOR_APP_AND_PATIENT_EXIST);
            }
            // 如果房间没人，则改为医生在
            if (VideoConsultCacheVO.NOT_EXIST == status) {
                cacheVO.setStatus(VideoConsultCacheVO.DOCTOR_APP_EXIST);
            }
            // 如果房间患者在,则改为APP端医生和患者都在
            else if (VideoConsultCacheVO.PATIENT_EXIST == status) {
                if (null == cacheVO.getStartTime()) {
                    cacheVO.setStartTime(System.currentTimeMillis());
                }
                cacheVO.setStatus(VideoConsultCacheVO.DOCTOR_APP_AND_PATIENT_EXIST);
            }
            videoConsultService.updateVideoConsultStatus(roomId, null, null, id);
            RedisUtil.hashOps().hset(VideoConsultConstant.VIDEO_CONSULT_PERSONNEL_CACHE_KEY  + roomId, userId, id);
        }
        // 患者
        else {
            log.info("患者进入房间, roomId:{}, userId:{}", roomId, userId);
            // 如果房间没人，则改为患者在
            if (VideoConsultCacheVO.NOT_EXIST == status) {
                cacheVO.setStatus(VideoConsultCacheVO.PATIENT_EXIST);
            }
            // 如果房间APP端医生在,则改为APP端医生和患者都在
            else if (VideoConsultCacheVO.DOCTOR_APP_EXIST == status) {
                // 第一次患者进入设置开始时间
                if (null == cacheVO.getStartTime()) {
                    cacheVO.setStartTime(System.currentTimeMillis());
                }
                cacheVO.setStatus(VideoConsultCacheVO.DOCTOR_APP_AND_PATIENT_EXIST);
                videoConsultService.updateVideoConsultStatus(roomId, null,
                    DrVideoConsult.VIDEO_CONSULT_STATUS_PROCESSING, null);
            }
            // 如果房间PC端医生在,则改为PC端医生和患者都在
            else {
                // 第一次患者进入设置开始时间
                if (null == cacheVO.getStartTime()) {
                    cacheVO.setStartTime(System.currentTimeMillis());
                }
                cacheVO.setStatus(VideoConsultCacheVO.DOCTOR_PC_AND_PATIENT_EXIST);
                videoConsultService.updateVideoConsultStatus(roomId, null,
                    DrVideoConsult.VIDEO_CONSULT_STATUS_PROCESSING, null);
            }
        }
        RedisUtil.valueOps().set(VideoConsultConstant.VIDEO_CONSULT_CACHE_KEY + roomId, JSON.toJSONString(cacheVO));
    }

    @Override
    public void outRoom(JSONObject json) {
        int roomId = json.getIntValue("RoomId");
        String userId = json.getString("UserId");
        boolean existsKey = RedisUtil.keyOps().existsKey(VideoConsultConstant.VIDEO_CONSULT_CACHE_KEY + roomId);
        if (existsKey) {
            String id = null;
            String cacheStr = RedisUtil.valueOps().getString(VideoConsultConstant.VIDEO_CONSULT_CACHE_KEY + roomId);
            VideoConsultCacheVO cacheVO = JSON.parseObject(cacheStr, VideoConsultCacheVO.class);
            Integer status = cacheVO.getStatus();
            boolean flag = false;
            if (VideoConsultUtil.containsDoctorPc(userId)) {
                log.info("PC端医生退出房间, roomId:{}, userId:{}", roomId, userId);
                if (VideoConsultCacheVO.DOCTOR_PC_AND_PATIENT_EXIST == status) {
                    cacheVO.setStatus(VideoConsultCacheVO.PATIENT_EXIST);
                    flag = true;
                } else if (VideoConsultCacheVO.DOCTOR_PC_EXIST == status) {
                    cacheVO.setStatus(VideoConsultCacheVO.NOT_EXIST);
                    flag = true;
                }
                id = VideoConsultUtil.getId(userId, VideoConsultUtil.DOCTOR_PC_PREFIX) + "";
            } else if (VideoConsultUtil.containsDoctor(userId)) {
                log.info("APP端医生退出房间, roomId:{}, userId:{}", roomId, userId);
                // 如果医生是被顶掉的则不更改状态
                if (VideoConsultCacheVO.DOCTOR_APP_AND_PATIENT_EXIST == status) {
                    cacheVO.setStatus(VideoConsultCacheVO.PATIENT_EXIST);
                    flag = true;
                } else if (VideoConsultCacheVO.DOCTOR_APP_EXIST == status) {
                    cacheVO.setStatus(VideoConsultCacheVO.NOT_EXIST);
                    flag = true;
                }
                id = VideoConsultUtil.getId(userId, VideoConsultUtil.DOCTOR_PREFIX) + "";
            } else {
                log.info("患者退出房间, roomId:{}, userId:{}", roomId, userId);
                if (VideoConsultCacheVO.DOCTOR_APP_AND_PATIENT_EXIST == status) {
                    cacheVO.setStatus(VideoConsultCacheVO.DOCTOR_APP_EXIST);
                    flag = true;
                } else if (VideoConsultCacheVO.DOCTOR_PC_AND_PATIENT_EXIST == status) {
                    cacheVO.setStatus(VideoConsultCacheVO.DOCTOR_PC_EXIST);
                    flag = true;
                } else {
                    cacheVO.setStatus(VideoConsultCacheVO.NOT_EXIST);
                    flag = true;
                }
                videoConsultService.sendDiscontinueMsg(roomId);
            }
            RedisUtil.valueOps().set(VideoConsultConstant.VIDEO_CONSULT_CACHE_KEY + roomId, JSON.toJSONString(cacheVO));
            // 如果医生两端同时登录时则不更改状态
            if (flag) {
                videoConsultService.updateVideoConsultStatus(roomId, null,
                    DrVideoConsult.VIDEO_CONSULT_STATUS_DISCONTINUE, id);
            }
            RedisUtil.hashOps().hdel(VideoConsultConstant.VIDEO_CONSULT_PERSONNEL_CACHE_KEY  + roomId, userId);
        } else {
            if (VideoConsultUtil.containsDoctor(userId)) {
                log.info("房间已解散, APP端医生退出房间, roomId:{}, userId:{}", roomId, userId);
            } else if (VideoConsultUtil.containsDoctorPc(userId)) {
                log.info("房间已解散, PC端医生退出房间, roomId:{}, userId:{}", roomId, userId);
            } else {
                log.info("房间已解散, 患者退出房间, roomId:{}, userId:{}", roomId, userId);
            }
        }
    }
}